
#include "m_socket.h"
#include "m_log.h"
#include "m_utils.h"

#include <pthread.h>

#include "lwip/sockets.h"
#include "lwip/netdb.h"

static int g_socket;

static void ReceiveDataTask(void *arg)
{
    m_log_d(M_SOCKET_H, "开始接收数据...\n");
    struct ReceiveDataListener *listener = (struct ReceiveDataListener *)arg;
    char recv_buf[SOCKE_REC_BUF_MAX];
    int r;

    do {
        r = lwip_read(g_socket, recv_buf, sizeof(recv_buf) - 1);
        if (r > 0) {
            #ifdef M_LOG_DEBUG
            unsigned char hex[(unsigned int)r * 2];
            m_to_hex(recv_buf, (unsigned int)r, hex);
            m_log_d(M_SOCKET_H, "receive data: %s\n", hex);
            #endif
            r = listener->onReceive(recv_buf, (unsigned int)r);
            #ifdef M_LOG_DEBUG
            if (r == 2) {
                break;
            }
            #endif
        }
    } while (1);
}

int m_connect(unsigned int port, const char *serverAddr)
{
    struct sockaddr_in addr = {0};
    addr.sin_family = AF_INET;
    addr.sin_port = PP_HTONS(port);
    addr.sin_addr.s_addr = inet_addr(serverAddr);
    g_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (g_socket < 0) {
        return 1;
    }
    m_log_d(M_SOCKET_H, "... allocated socket\n");
    if (connect(g_socket, (struct sockaddr*)&addr, sizeof(addr)) != 0) {
        m_log_e(M_SOCKET_H, "... socket connect failed errno=%d\n", errno);
        lwip_close(g_socket);
        return 1;
    }
    m_log_d(M_SOCKET_H, "... connected\n");
    //if (lwip_write(s, g_request, strlen(g_request)) < 0) {
    //    lwip_close(s);
    //    return 1;
    //}
    //printf("... socket send success");
    struct timeval receiving_timeout;
    /* 5S Timeout */
    receiving_timeout.tv_sec = 5;
    receiving_timeout.tv_usec = 0;
    if (setsockopt(g_socket, SOL_SOCKET, SO_RCVTIMEO, &receiving_timeout, sizeof(receiving_timeout)) < 0) {
        m_log_e(M_SOCKET_H, "... failed to set socket receiving timeout\n");
        lwip_close(g_socket);
        return 1;
    }
    m_log_d(M_SOCKET_H, "... set socket receiving timeout success\n");
    return 0;
}

int m_startReceiveData(struct ReceiveDataListener *listener)
{
    pthread_t thread = 0;
    pthread_attr_t attr = {0};
    int r;

    r = pthread_attr_init(&attr);
    if (r != 0) {
        m_log_e(M_SOCKET_H, "pthread_attr_init fail: %d\n", r);
        return 1;
    }
    m_log_d(M_SOCKET_H, "pthread_create...\n");
    r = pthread_create(&thread, &attr, ReceiveDataTask, listener);
    if (r != 0) {
        m_log_e(M_SOCKET_H, "pthread_create fail: %d\n", r);
        return 1;
    }
    return 0;
}